package com.xy.service.impl;

import com.google.gson.Gson;
import com.xy.constant.enums.DocxTemplateEnum;
import com.xy.constant.enums.DocxTypeAndLabelEnum;
import com.xy.dto.DocxContentDTO;
import com.xy.entity.DocxContentEntity;
import com.xy.exception.enums.DocxExceptionEnum;
import com.xy.form.DocxContentForm;
import com.xy.repository.IDocxContentDao;
import com.xy.service.IDocService;
import com.xy.service.IFileHandlerService;
import com.xy.utils.AssertUtil;
import com.xy.utils.ConfigUtil;
import com.xy.utils.DocHandlerUtil;
import com.xy.vo.FileVO;
import com.xy.vo.WritedDocContentVO;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import org.springframework.mock.web.MockMultipartFile;

@Service
public class DocServiceImpl implements IDocService {
    private static final String prefixPath = ConfigUtil.readProperty("file_path");
    private final IDocxContentDao docxContentDao;
    private final IFileHandlerService fileUploadService;

    @Autowired
    public DocServiceImpl(IDocxContentDao docxContentDao, IFileHandlerService fileUploadService) {
        this.docxContentDao = docxContentDao;
        this.fileUploadService = fileUploadService;
    }

    /**
     * 读取模板文档内容，匹配提取label内容，并保存到数据库中
     * @param typeId 模板id
     * @return DocxContentDTO
     */
    @Override
    public DocxContentDTO readAndSaveDocContent(Integer typeId) {
        String[] labels = DocxTypeAndLabelEnum.getDocxKeyStringsByType(typeId);
        AssertUtil.assertNotNull(labels, DocxExceptionEnum.DOCX_TYPE_NOT_EXIST);
        String docTemplateName = DocxTemplateEnum.getTemplateNameByType(typeId);
        AssertUtil.assertNotNull(docTemplateName, DocxExceptionEnum.DOCX_TYPE_NOT_EXIST);
        String docPath = prefixPath + "/" + docTemplateName;
        DocxContentEntity docxContentEntity = null;
        try {
            Map<String,String> labelMap = DocHandlerUtil.getAllLabel(new XWPFDocument(new FileInputStream(docPath)), labels);
            String docxContent = new Gson().toJson(labelMap);
            docxContentEntity = docxContentDao.save(new DocxContentEntity(new DocxContentDTO(docxContent, typeId)));
            //labelMap.forEach((key, value) -> System.out.println(key + ": " + value));
        } catch (IOException e) {
            e.printStackTrace();
        }
        AssertUtil.assertNotNull(docxContentEntity, DocxExceptionEnum.DOCX_SAVE_FAIL);
        return new DocxContentDTO(docxContentEntity.getDocContent(), docxContentEntity.getType());
    }

    @Override
    public WritedDocContentVO writeDocContent(DocxContentForm docxContentForm) {
        String docTemplateName = DocxTemplateEnum.getTemplateNameByType(docxContentForm.getType());
        AssertUtil.assertNotNull(docTemplateName, DocxExceptionEnum.DOCX_TYPE_NOT_EXIST);
        String docPath = prefixPath + "/" + docTemplateName;
        AssertUtil.assertNotNull(docxContentForm.getDocContent(), DocxExceptionEnum.DOCX_LABEL_NOT_EXIST);
        Map<String,String> docxContent = new Gson().fromJson(docxContentForm.getDocContent(), Map.class);
        try ( FileInputStream fis = new FileInputStream(docPath);
              XWPFDocument doc = new XWPFDocument(fis)){
            DocHandlerUtil.writeDocContent(doc, docxContent);
            try(FileOutputStream fos = new FileOutputStream("output.docx")
                ){
                doc.write(fos);
                // 创建MultipartFile
                byte[] fileContent = java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("output.docx"));
                MultipartFile multipartFile = new MockMultipartFile("file", "output.docx",
                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document", fileContent);
                FileVO fileVO = fileUploadService.importFile(multipartFile);
                DocxContentEntity docxContentEntity = docxContentDao.save(new DocxContentEntity(new DocxContentDTO(docxContentForm.getDocContent(), docxContentForm.getType())));
                return new WritedDocContentVO(fileVO, new DocxContentDTO(docxContentEntity));
            }
        } catch (Exception e) {
            AssertUtil.assertTrue(false, DocxExceptionEnum.DOCX_WRITE_FAIL);
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public DocxContentDTO getDocContent(Long id) {
        return null;
    }

    @Override
    public DocxContentDTO updateDocContentAndWriteDoc(DocxContentDTO docxContentDTO) {
        return null;
    }
}
